<template>
  <div class="map-popup-container" ref="containerRef" v-if="visible">
    <!-- <svg v-show="showAnchorLine" class="line-wrap">
      <line ref="lineRef" stroke="#9fe511" stroke-width="2" stroke-dasharray="10,10"></line>
    </svg> -->
    <svg v-show="showAnchorLine" class="line-wrap">
      <polygon ref="lineRef" style="fill: #efefef; stroke-width: 2; stroke: rgba(0, 0, 0, 0.15)"></polygon>
    </svg>
    <div class="map-popup-wrapper" ref="popupRef" :style="{ top: popupTop + 'px', left: popupLeft + 'px' }">
      <div class="header-wrapper no-select" @mousedown="handleMouseDown">
        <slot name="header">
          <span>自定义弹框</span>
        </slot>
        <el-icon class="close-icon" @click="handleClose">
          <Close />
        </el-icon>
      </div>

      <div class="content-wrapper">
        <slot>自定义内容</slot>
      </div>
      <div class="footer-wrapper no-select">
        <slot name="footer"></slot>
      </div>
    </div>
    <div ref="startPointRef" class="start-point"></div>
  </div>
</template>

<script setup lang="ts">
import * as Cesium from 'cesium';
import useMapStore from '@/store/modules/map';
const mapStore = useMapStore();

const emits = defineEmits(['close']);
const visible = defineModel({ default: true });

const props = defineProps({
  position: {
    type: Cesium.Cartesian3,
    required: true
  },
  offset: {
    type: Object,
    default: () => ({ x: 0, y: -10 })
  },
  showCloseButton: {
    type: Boolean,
    default: true
  },
  initX: {
    type: Number,
    default: 100
  },
  initY: {
    type: Number,
    default: -300
  },
  showAnchorLine: {
    type: Boolean,
    default: true
  },
  anchorWidth: {
    type: Number,
    default: 30
  }
});

const popupTop = ref(props.initY);
const popupLeft = ref(props.initX);
const containerRef = ref();
const popupRef = ref();
const lineRef = ref();
const startPointRef = ref();

/**
 * @description 关闭事件
 */
const handleClose = () => {
  visible.value = false;
  emits('close');
};

let isMove = false;
const handleMouseDown = (e: MouseEvent) => {
  const target = popupRef.value;
  // let _move = false;

  let startX = e.clientX - parseInt(window.getComputedStyle(target).left);
  let startY = e.clientY - parseInt(window.getComputedStyle(target).top);
  // let startX = e.clientX
  // let startY = e.clientY

  const _mouseMove = (moveEvent: MouseEvent) => {
    // _move = true;
    isMove = true;
    let newX = moveEvent.clientX - startX;
    let newY = moveEvent.clientY - startY;

    popupTop.value = newY;
    popupLeft.value = newX;
    // target.style.setProperty('top', newY + 'px');
    // target.style.setProperty('left', newX + 'px');

    updateLine();
  };

  const _mouseUp = () => {
    // _move = false;
    isMove = false;
    document.removeEventListener('mousemove', _mouseMove);
    document.removeEventListener('mouseup', _mouseUp);
    // document.removeEventListener('selectstart', noSelect);
  };
  document.addEventListener('mousemove', _mouseMove);
  document.addEventListener('mouseup', _mouseUp);
  // document.addEventListener('selectstart', noSelect);
};

const updateLine = () => {
  // 起点位置地图上的标记点
  const startPoint = getElementPosition(startPointRef.value, containerRef.value);
  // 重点位置 弹窗的中心点
  const endPoint = getElementPosition(popupRef.value, containerRef.value);
  /**假如希望修改连线起止点的位置 修改以下的 start、end 的求取方式*/
  const start = { x: startPoint.left, y: startPoint.top };
  const end = { x: endPoint.left + endPoint.width / 2, y: endPoint.top + endPoint.height / 2 };
  // 设置线条的起始和结束位置
  // setAttributes(lineRef.value, { x1: start.x + props.offset.x, y1: start.y + props.offset.y, x2: end.x, y2: end.y });

  let points = '';
  // 右上角 以及 左下角
  if ((end.x > start.x && end.y < start.y) || (end.x < start.x && end.y > start.y)) {
    points = `${start.x + props.offset.x},${start.y + props.offset.y} ${end.x - props.anchorWidth},${end.y} ${end.x},${end.y} ${end.x},${end.y + props.anchorWidth} ${start.x + props.offset.x},${start.y + props.offset.y}`;
  } else {
    // 左上角 以及 右下角
    points = `${start.x + props.offset.x},${start.y + props.offset.y} ${end.x},${end.y - props.anchorWidth} ${end.x},${end.y} ${end.x - props.anchorWidth},${end.y} ${start.x + props.offset.x},${start.y + props.offset.y}`;
  }

  setAttributes(lineRef.value, {
    'points': points
  });
  // const path = document.getElementById('path'); // 或 querySelector
  // if (path) {
  //   path.setAttribute('d', 'M20,20 L100,100');
  // }
};

// 获取元素相对于父元素的位置
const getElementPosition = (element: HTMLElement, parent?: HTMLElement) => {
  let offsetLeft = 0;
  let offsetTop = 0;
  let offsetWidth = 0;
  let offsetHeight = 0;

  if (parent) {
    while (element && element !== parent) {
      offsetLeft += element.offsetLeft;
      offsetTop += element.offsetTop;
      offsetWidth += element.offsetWidth;
      offsetHeight += element.offsetHeight;
      element = element.offsetParent as HTMLElement;
    }
  } else {
    offsetLeft += element.offsetLeft;
    offsetTop += element.offsetTop;
    offsetWidth += element.offsetWidth;
    offsetHeight += element.offsetHeight;
  }

  return { left: offsetLeft, top: offsetTop, width: offsetWidth, height: offsetHeight };
};

let listen = null;

onMounted(() => {
  const viewer: Cesium.Viewer = mapStore.getMap();
  const position = props.position;

  nextTick(() => {
    // const { height } = popupRef.value.getBoundingClientRect();
    // 地图渲染事件，绑定popup位置，让弹窗能够随地图移动缩小放大
    // 初始化标记线条
    listen = viewer.scene.postRender.addEventListener(() => {
      if (Cesium.defined(position) && containerRef.value) {
        updateLine();
        let windowPosition = viewer.scene.cartesianToCanvasCoordinates(position);
        containerRef.value.style.left = windowPosition.x + 'px';
        containerRef.value.style.top = windowPosition.y + 'px';
      }
    });
  });
});

const setAttributes = (element: HTMLElement, attributes: Record<string, string | number>) => {
  if (!element) return;
  Object.entries(attributes).forEach(([key, value]) => {
    element.setAttribute(key, value.toString());
  });
};

onBeforeUnmount(() => {
  listen();
  listen = null;
});
</script>

<style scoped lang="scss">
.map-popup-container {
  user-select: none;
  position: relative;
  height: 0;

  .start-point {
    position: absolute;
  }
}
.map-popup-wrapper {
  position: absolute;
  border-radius: 5px;
  width: 340px;
  box-shadow:
    rgba(0, 0, 0, 0.12) 0px 1px 3px,
    rgba(0, 0, 0, 0.24) 0px 1px 2px;
}

.header-wrapper {
  z-index: 2;
  position: relative;
  display: flex;
  justify-content: space-between;
  padding: 0 5px;
  align-items: center;
  width: 100%;
  height: 32px;
  background-color: #efefef;
  font-size: 15px;
  background-color: rgba($color: #000000, $alpha: 0.3);
  font-family: 微软雅黑;
  cursor: move;
  box-shadow:
    rgba(0, 0, 0, 0.12) 0px 1px 3px,
    rgba(0, 0, 0, 0.24) 0px 1px 2px;
}

// .content-wrapper {
//   border-bottom: 5px;
// }

.footer-wrapper {
  padding: 0 5px;
  align-items: center;
  width: 100%;
  // background-color: rgba($color: #ffffff, $alpha: 0.3);
  font-size: 15px;
  font-family: 微软雅黑;
}

.close-icon {
  position: absolute;
  right: 5px;
  cursor: pointer;
  font-size: 20px;
  // transform: scale(0.9);
  transition: transform 200ms ease;

  &:hover {
    transform: scale(1.2);
    background-color: rgba($color: #000000, $alpha: 0.2);
  }
}

.line-wrap {
  user-select: none;
  pointer-events: none;
  position: absolute;
  left: 0;
  top: 0;
  width: 1px;
  height: 1px;
  overflow: visible;
  // box-shadow:
  //   rgba(0, 0, 0, 0.12) 0px 1px 3px,
  //   rgba(0, 0, 0, 0.24) 0px 1px 2px;
}
</style>
